<?php
/**
 * @author: Gardennet
 * @date: 16-12-15
 * @email: lwp8800@sina.com
 */
namespace App\Services\Wechat;

/**
 * 微信服务
 * Class WechatMpTrait
 * @package App\Services\Wechat
 */
Trait WechatMpTrait
{
    /**
     * 长链接转短链接接口
     * @param string $url  链接
     * false 失败
     * true  返回短连接
     * 认证服务号独有权限
     * @return bool|string
     */
    public function getShortUrl(string $url) : string
    {
        $result = $this->getWechatInstance()->getShortUrl($url);

        if(!empty($result)){
            return $result;
        }

        return false;
    }

    /**
     * 微信服务器请求签名检测
     * @return string
     */
    public function checkSignature() : string
    {
        $status=$this->getWechatInstance()->checkSignature();
        if($status){
            $echostr = $_GET['echostr'];
            return $echostr;
        }

        return '';
    }

    /**
     * 发送客服消息
     *
     * @param string|array $openid    粉丝openid
     * @param array|string $msg 消息
     *
     * 消息格式
     * $msg=[
     *   'first'=>['value'=>'恭喜您充值成功！'],
     *   'money'=>['title' => '充值金额', 'value'=>$data['price'].'元'],
     *   'product'=>['title' => '充值方式', 'value'=>$data['pay_type']],
     *   'remark'=>['value'=>"充值时间:".date('Y-m-d H:i:s',$data['time'])."\n\n谢谢您对我们的支持！"],
     *   ];
     * @param string $url        链接
     * @return array
     */
    public function sendCustomMessage($openid, $msg, string $url = '') : array
    {
        if(empty($openid)){

            return ['code'=>1,'msg'=>'参数错误,粉丝openid不能为空'];
        }

        if(empty($msg)){
            return ['code'=>1,'msg'=>'参数错误,请根据模板规则完善消息内容'];
        }

        $content = "";
        if (is_array($msg)) {
            foreach ($msg as $key => $value) {
                if (!empty($value['title'])) {
                    $content .= $value['title'] . ":" . $value['value'] . "\n";
                } else {
                    $content .= $value['value'] . "\n";
                    if ($key == 0) {
                        $content .= "\n";
                    }
                }
            }
        } else {
            $content = $msg;
        }
        if (!empty($url)) {
            $content .= "<a href='{$url}'>点击查看详情</a>";
        }

        $wechat=$this->getWechatInstance();

        if(is_array($openid)){
            foreach($openid as $v){
                if (empty($v)) {
                    continue;
                }
                $wechat->sendMessage(["touser" => $v, "msgtype" => "text", "text" => ['content' => $content]]);
                usleep(500000);//500ms
            }
        }else{
            $wechat->sendMessage(["touser" => $openid, "msgtype" => "text", "text" => ['content' => $content]]);
        }

        return ['code'=>0,'msg'=>'发送成功'];

    }

    /**
     * 发送模板消息
     *
     * @param array|string $openid    粉丝openid
     * @param string $template_id    模板id
     * @param array $msg 消息
     *
     * 消息格式
     * $msg=[
     *   'first'=>['value'=>'恭喜您充值成功！'],
     *   'money'=>['title' => '充值金额', 'value'=>$data['price'].'元'],
     *   'product'=>['title' => '充值方式', 'value'=>$data['pay_type']],
     *   'remark'=>['value'=>"充值时间:".date('Y-m-d H:i:s',$data['time'])."\n\n谢谢您对我们的支持！"],
     *   ];
     * @param string $url        链接
     * @return array
     */
    public function sendTplMessage($openid,string $template_id,array $msg,string $url = '') :array
    {
        if(empty($openid)){
            return json_encode(['code'=>1,'msg'=>'参数错误,粉丝openid不能为空']);
        }

        if(empty($template_id)){
            return json_encode(['code'=>1,'msg'=>'参数错误,模板id不能为空']);
        }

        if(empty($msg) || !is_array($msg)) {
            return json_encode(['code'=>1,'msg'=>'参数错误,请根据模板规则完善消息内容']);
        }

        $wechat = $this->getWechatInstance();

        if(is_array($openid)){
            foreach($openid as $v){
                if (empty($v)) {
                    continue;
                }
                $wechat->sendTemplateMessage( [
                    "touser"=>$v,
                    "template_id"=>$template_id,
                    "url" => trim($url),
                    "data"=> $msg
                ]);
                usleep(500000);//500ms
            }

        }else{
            $wechat->sendTemplateMessage( [
                "touser"=>$openid,
                "template_id"=>$template_id,
                "url" => trim($url),
                "data"=> $msg
            ]);
        }

        return ['code'=>0,'msg'=>'发送成功'];
    }

    /**
     * 微信Oauth获取code
     * @param string $redirectUrl 回调地址
     * @param string $type 类型   snsapi_userinfo|snsapi_base
     * @return array
     */
    public function wechatGetCode(string $redirectUrl,string $type='snsapi_userinfo') : array
    {
        $code = !empty($this->request->query->get('code'))?$this->request->query->get('code'):$this->request->get('code');//授权code
        if(empty($code)){
            $url=$this->getWechatInstance()->getOauth2AuthorizeUrl($redirectUrl,'authorize',$type);
            return ['code'=>0,'redirect'=>$url];
        }else{
            return ['code'=>$code];
        }
    }

    /**
     * 获取openid
     * @param string $redirectUrl 回调地址
     * @param string $type 类型   snsapi_userinfo|snsapi_base
     * @return array|bool
     */
    public function getOpenidByCode(string $redirectUrl,string $type='snsapi_userinfo')
    {
        $code = $this->request->query->get('code');//授权code
        $oauth=$this->wechatGetCode($redirectUrl,$type);
        if(!empty($oauth['code']) && !empty($code)){
            $response=$this->getWechatInstance()->getOauth2AccessToken($oauth['code']);
            return $response;
        }elseif(!empty($oauth['redirect']) && empty($oauth['code'])){
            header("Location: ".$oauth['redirect']."");exit;
        }
    }

    /**
     * 微信Oauth授权登录
     * @param string $redirectUrl 回调地址
     * @param string $to          成功后跳转地址
     * @return array|bool
     */
    public function wechatLogin(string $redirectUrl,string $to='')
    {
        $code = $this->request->query->get('code');//授权code

        if(!isset($code)){
            $url=$this->getWechatInstance()->getOauth2AuthorizeUrl($redirectUrl, 'authorize', 'snsapi_userinfo');
            header("Location: ".$url."");exit;
        }else{
            return $this->wechatLoginByCode($code,$to);
        }
    }

    /**
     * 微信Oauth授权登录
     * @param string $code 授权code
     * @param string $to   成功后跳转地址
     * @return array
     */
    public function wechatLoginByCode(string $code,string $to='') : array
    {
        if(!empty($code)){
            $response=$this->getWechatInstance()->getOauth2AccessToken($code);
            if(empty($response)){
                return ['code'=>'1','msg'=>'获取网页授权access_token失败'];
            }
            $openid=$response['openid'];
            $access_token=$response['access_token'];

            if($openid && $access_token){
                $userinfo=$this->getWechatInstance()->getSnsUserInfo($openid,$access_token);
                if(empty($userinfo)){
                    return ['code'=>1,'msg'=>'获取用户信息失败'];
                }

                $user_info=$this->getUserInfoByOpenId($userinfo['openid']);
                $userinfo['subscribe']=$user_info['subscribe'];
                $userinfo['subscribe_time']=$user_info['subscribe_time'];
                $userinfo['groupid']=$user_info['groupid'];

                $userinfo['nickname']=$this->removeEmoji($userinfo['nickname']);
                $userinfo['headimgurl'] = preg_replace('/^http:/', 'https:', $userinfo['headimgurl']);

                return ['code'=>0,'redirect'=>$to,'userinfo'=>$userinfo];
            }
        }
    }


    /**
     * 获取用户基本信息
     * @param string $openid openid
     * @return array
     */
    public function getUserInfoByOpenId(string $openid) : array
    {
        if(empty($openid)){
            return ['code'=>1,'msg'=>'openid不能为空'];
        }

        if(!empty($openid)){
            $user_info=$this->getWechatInstance()->getUserInfo($openid);

            $user_info['subscribe']=$user_info['subscribe']==1?$user_info['subscribe']:0;
            $user_info['subscribe_time']=!empty($user_info['subscribe_time'])?$user_info['subscribe_time']:0;
            $user_info['groupid']=!empty($user_info['groupid'])?$user_info['groupid']:0;

            return $user_info;
        }
    }


    /**
     * 生成js 必需的config
     * 只需在视图文件输出JS代码:
     *  wx.config(<?= json_encode($wehcat->jsApiConfig()) ?>); // 默认全权限
     *  wx.config(<?= json_encode($wehcat->jsApiConfig([ // 只允许使用分享到朋友圈功能
     *      'jsApiList' => [
     *          'onMenuShareTimeline'
     *      ]
     *  ])) ?>);
     * @param array $config
     * @param bool $debug
     * @param string  $appoint_url    指定的链接
     * @return array
     */
    public function jsApiConfig($config=[],$debug=false,$appoint_url = '') : array
    {
        return $this->getWechatInstance()->jsApiConfig($config,$debug,$appoint_url);
    }

    /**
     * 公众平台
     * 自定义菜单创建接口(创建菜单)
     * @param array $buttons 菜单结构字符串
     * @return array
     */
    public function createMenu($buttons) : array
    {
        return $this->getWechatInstance()->createMenu($buttons);
    }

    /**
     * 公众平台
     * 自定义菜单查询接口(获取菜单)
     * @return array|bool
     */
    public function getMenu()
    {
        return $this->getWechatInstance()->getMenu();
    }

    /**
     * 公众平台
     * 自定义菜单删除接口(删除菜单)
     * @return bool
     */
    public function deleteMenu() : bool
    {
        return $this->getWechatInstance()->deleteMenu();
    }

    /**
     * 获取微信开放平台预授权码
     * @return string
     */
    public function getComponentPreAuthCode($force = false) : string
    {
        return $this->getOpenInstance()->getComponentPreAuthCode($force);
    }

    /**
     * 获取授权方的公众号帐号基本信息
     * $authInfo
     * @return array|null
     */
    public function getAuthorizerInfo($authInfo)
    {
        return $this->getOpenInstance()->getAuthorizerInfo($authInfo);
    }

    /**
     * 获取微信开放平台授权信息
     * $authCode
     * @return array|null
     */
    public function getComponentAuthInfo($authCode)
    {
        return $this->getOpenInstance()->getComponentAuthInfo($authCode);
    }

    /**
     * 获取微信开放平台（刷新）授权公众号的接口调用凭据（令牌）
     * @return string|null
     */
    public function getAuthorizerToken($authInfo)
    {
        return $this->getOpenInstance()->getAuthorizerToken($authInfo);
    }

    /**
     * 开放平台
     * 自定义菜单创建接口(创建菜单)
     * @param array $buttons 菜单结构字符串
     * @param string $authAccessToken 授权公众号的接口调用凭据
     * @return array
     */
    public function createOpenMenu($buttons,$authAccessToken) : array
    {
        return $this->getOpenInstance()->createMenu($buttons,$authAccessToken);
    }

    /**
     * 开放平台
     * 自定义菜单查询接口(获取菜单)
     * @param string $authAccessToken 授权公众号的接口调用凭据
     * @return array|bool
     */
    public function getOpenMenu($authAccessToken)
    {
        return $this->getOpenInstance()->getMenu($authAccessToken);
    }

    /**
     * 开放平台
     * 自定义菜单删除接口(删除菜单)
     * @param string $authAccessToken 授权公众号的接口调用凭据
     * @return bool
     */
    public function deleteOpenMenu($authAccessToken) : bool
    {
        return $this->getOpenInstance()->deleteMenu($authAccessToken);
    }


    public function removeEmoji($text) {

        $clean_text = "";

        // Match Emoticons
        $regexEmoticons = '/[\x{1F600}-\x{1F64F}]/u';
        $clean_text = @preg_replace($regexEmoticons, '', $text);

        // Match Miscellaneous Symbols and Pictographs
        $regexSymbols = '/[\x{1F300}-\x{1F5FF}]/u';
        $clean_text = @preg_replace($regexSymbols, '', $clean_text);

        // Match Transport And Map Symbols
        $regexTransport = '/[\x{1F680}-\x{1F6FF}]/u';
        $clean_text = @preg_replace($regexTransport, '', $clean_text);

        // Match Miscellaneous Symbols
        $regexMisc = '/[\x{2600}-\x{26FF}]/u';
        $clean_text = @preg_replace($regexMisc, '', $clean_text);

        // Match Dingbats
        $regexDingbats = '/[\x{2700}-\x{27BF}]/u';
        $clean_text = @preg_replace($regexDingbats, '', $clean_text);

        $clean_text = $this->filterEmoji($clean_text);

        return $clean_text;
    }

    private function filterEmoji($str)
    {
        $str = preg_replace_callback(
            '/./u',
            function (array $match) {
                return strlen($match[0]) >= 4 ? '' : $match[0];
            },
            $str);

        return $str;
    }
}